#include "include/SignalSlot.h"
#include <mutex>
#include <thread>

namespace Tool
{

Signal::~Signal()
{
    std::lock_guard<std::mutex> lock(m_mutex);
    for (auto& conn : m_connections)
    {
        if (conn) conn->disconnect();
    }
}

void Signal::emit(std::shared_ptr<MemberSlotEvent> event)
{
    std::lock_guard<std::mutex> lock(m_mutex);
    for (auto& conn : m_connections)
    {
        if (conn)
        {
            conn->invoke(event);
        }
    }
}

void Connection::invoke(std::shared_ptr<MemberSlotEvent> event)
{
    if (!m_connected)
    {
        return;
    }

    if(m_type == ConnectionType::Direct || (m_type == ConnectionType::Auto && !m_loop))
    {
        m_slot->Call(event);
    }
    else
    {
        if (!m_loop)
        {
            return;
        }
        event->slot_base = m_slot;
        m_loop->PostEvent(event);
    }
}

void Connection::disconnect()
{
    m_connected = false;
}

void RegisterSignalSlotEvents(EventLoop* loop)
{
    if (!loop)
    {
        return;
    }

    loop->RegisterHandler(EventType::SignalSlot,[](std::shared_ptr<Event> event)
    {
        std::shared_ptr<MemberSlotEvent> member_slot = std::dynamic_pointer_cast<MemberSlotEvent>(event);
        if (member_slot)
        {
            member_slot->slot_base->Call(member_slot);
        }
    });
}

}  // namespace Tool
